package routerServer

import (
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-common/commMqttRpc"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/AjaxResult"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Json"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Uuid"
	"github.com/afex/hystrix-go/hystrix"
	"github.com/gin-gonic/gin"
	"go-fox-edge-iot-gateway/commEnv"
	"go-fox-edge-iot-gateway/token"
	"io"
	"net/http"
	"strings"
)

type routerHandler struct {
	router map[string]interface{}
	tls    *http.Transport
}

func (e *routerHandler) registerRouter() {
	url := ""

	// 检测：是否已经注册该路由
	_, ok := e.router[url]
	if ok {
		return
	} else {
		e.router[url] = ""
	}

	engine.GET(url+"/*res", func(context *gin.Context) {
		e.handleRequest(context, "GET")
	})
	engine.DELETE(url+"/*res", func(context *gin.Context) {
		e.handleRequest(context, "DELETE")
	})
	engine.PUT(url+"/*res", func(context *gin.Context) {
		e.handleRequest(context, "PUT")
	})
	engine.POST(url+"/*res", func(context *gin.Context) {
		e.handleRequest(context, "POST")
	})
}

func (e *routerHandler) handleRequest(context *gin.Context, method string) {
	res := context.Param("res")
	commandName := "" + res

	// 使用 Hystrix 实现服务熔断
	hystrix.ConfigureCommand(commandName, hystrix.CommandConfig{
		Timeout:               60 * 1000, // 超时时间（毫秒）
		MaxConcurrentRequests: 10,        // 最大并发请求数
		ErrorPercentThreshold: 25,        // 错误百分比阈值
	})

	hystrix.Do(commandName, func() error {
		// 获取客户端传入的 token
		tokenStr := context.GetHeader("Authorization")
		if strings.HasPrefix(tokenStr, "Bearer ") {
			tokenStr = tokenStr[len("Bearer "):]
		}

		// 取出body
		requestBody, err := io.ReadAll(context.Request.Body)
		if err != nil {
			return err
		}

		requestVO := &commMqttRpc.RestfulLikeRequestVO{}
		requestVO.Topic = commEnv.Service.Topic.Request
		requestVO.Uuid = Uuid.RandomUUID()
		requestVO.Method = method
		requestVO.Body = Json.BuildMapByJson(string(requestBody))
		requestVO.ExecuteTime = 10 * 1000

		if context.Request.URL.RawQuery != "" {
			requestVO.Resource = res + "?" + context.Request.URL.RawQuery
		} else {
			requestVO.Resource = res
		}

		respondVO, err := commMqttRpc.Request(requestVO)
		if err != nil {
			return err
		}

		// 默认格式：以body返回
		respondBody := Json.BuildJson(respondVO.Body)

		// 将目标服务的响应返回给客户端
		context.Status(http.StatusOK)
		_, err = context.Writer.Write([]byte(respondBody))
		return err
	}, func(err error) error {
		// 处理熔断
		respondError(context, err)
		return nil
	})
}

func (e *routerHandler) buildRequest(context *gin.Context, method, relativePath, redirectPath, res string) (*http.Request, error) {
	authMode := "gateway"
	val, ok := e.router[relativePath]
	if ok {
		authMode = val.(string)
	}

	if authMode == "gateway" {
		// 获取客户端传入的 token
		tokenStr := context.GetHeader("Authorization")
		if len(tokenStr) < len("Bearer ") {
			return nil, errors.New("无效的token")
		}

		// 检测：是否包好Bearer，POSTMAN发送就可能包含
		if "Bearer " == tokenStr[0:len("Bearer ")] {
			tokenStr = tokenStr[len("Bearer "):]
		}

		// 验证toke的有效性
		tkn, clm, err := token.ParseToken(tokenStr)
		if err != nil {
			return nil, err
		}
		if !tkn.Valid || clm.Valid() != nil {
			return nil, errors.New("无效的token")
		}

		// 申请转发请求
		request, err := e.newRequest(context, method, redirectPath, res)
		if err != nil {
			return nil, err
		}

		// 添加认证 token
		request.Header.Set("Authorization", tokenStr)
		request.Header.Set("Content-Type", "application/json")
		request.Header.Set("Client-IP", context.ClientIP())

		return request, nil
	} else {
		// 申请转发请求
		request, err := e.newRequest(context, method, redirectPath, res)
		if err != nil {
			return nil, err
		}

		// 添加认证 token
		request.Header.Set("Authorization", context.GetHeader("Authorization"))
		request.Header.Set("Content-Type", "application/json")
		request.Header.Set("Client-IP", context.ClientIP())
		return request, nil
	}

	return nil, errors.New("鉴权模式不正确")
}

func respondError(context *gin.Context, err error) {
	data := AjaxResult.Error("内部服务转发错误", err.Error())
	context.JSON(http.StatusServiceUnavailable, data)
}

func (e *routerHandler) newRequest(context *gin.Context, method string, redirectPath string, res string) (*http.Request, error) {
	if method == "GET" || method == "DELETE" {
		url := redirectPath + res
		if context.Request.URL.RawQuery != "" {
			url += "?" + context.Request.URL.RawQuery
		}

		// 创建请求
		req, err := http.NewRequest(method, url, nil)
		if err != nil {
			return nil, err
		}

		return req, nil
	}
	if method == "POST" || method == "PUT" {
		// 创建请求
		req, err := http.NewRequest(method, redirectPath+res, context.Request.Body)
		if err != nil {
			return nil, err
		}

		return req, nil
	}

	return nil, errors.New("不支持的操作")

}
